package org.malred.v5.server;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * minicat主类
 */
public class Bootstrap {
    /**
     * socket监听的端口号
     */
    private int port = 8080;
    private Map<String, HttpServlet> servletMap = new HashMap<>();

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    /**
     * minicat启动需要初始化展开的一些操作
     */
    public void start() throws Exception {
        //加载解析配置文件,web.xml
        loadServlet();
        int corePoolSize = 10;//初始线程池大小
        int maximumPoolSize = 50;//最大线程数
        long keepAliveTime = 100L;//最大保留时间
        TimeUnit unit = TimeUnit.SECONDS;//时间单位
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(50);//请求队列
        ThreadFactory threadFactory = Executors.defaultThreadFactory();//线程工厂
        RejectedExecutionHandler handle = new ThreadPoolExecutor.AbortPolicy();//拒绝策略
        //定义线程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handle
        );
        /*
         * minicat v1.0,http://localhost:8080,返回固定字符串到页面
         */
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("minicat start on port: " + port);
        /**
         * Minicat5.0版本
         * 需求: 线程池
         */
        while (true) {
            Socket socket = serverSocket.accept();
            RequestProcessor requestProcessor = new RequestProcessor(socket, servletMap);
//            requestProcessor.start();
            threadPoolExecutor.execute(requestProcessor);
        }
    }

    /**
     * 加载解析web.xml,初始化servlet
     */
    private void loadServlet() throws Exception {
        //加载配置文件
        InputStream resourceAsStream =
                this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            //获取根元素
            Element rootElement = document.getRootElement();
            //获取servlet标签list
            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element = selectNodes.get(i);
                //<servlet-name>malguy</servlet-name>
                Element servletNameEle = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletNameEle.getStringValue();
                //<servlet-class>server.MiniServlet</servlet-class>
                Element servletClassEle = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletClassEle.getStringValue();
                //根据servlet-name找到对应的mapping,找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode
                        ("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                //url-pattern
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}